#include "geminai_adc.h"
#include <stdio.h>

#define 	NTC_R_NORMAL	    10000.0//2005.0//热敏电阻标称阻值10K(25度时)
#define 	NTC_B			    3435//3839.0//3950.0//热敏电阻系数
#define 	NTC_KA			    273.15//开尔文绝对0度
#define		NTC_T_NORMAL	    25.0//标称温度25度
#define 	NTC_T_NORMAL_K	    (NTC_KA+NTC_T_NORMAL)//标称温度换算成开尔文温度
#define     ADC_RES_UP_V2       51000.0//100000.0;//100000.0;//100K电阻(第二代硬件版本)
#define 	REF_VOL				330//参考电压3.3V放大100倍
#define     SAMPLE_NUM          16 //采样次数

#define NTC0_CHANNEL            ADC_CHANNEL_0
#define ADC_BATTERY_CHANNEL     ADC_CHANNEL_1
#define ADC_24V_INT_CHANNEL     ADC_CHANNEL_2
#define NTC_TA_CHANNEL          ADC_CHANNEL_3
#define ADC_VN0_CHANNEL         ADC_CHANNEL_4
#define ADC_LIGHT_CHANNEL       ADC_CHANNEL_4
#define NTC1_CHANNEL            ADC_CHANNEL_6
#define NTC2_CHANNEL            ADC_CHANNEL_7
#define ADC_3_3V_IN_CHANNEL            ADC_CHANNEL_8

//WiFi与ADC2不能同时使用
#define USE_ADC2            0

const static char *TAG = "ADC";

adc_oneshot_unit_handle_t adc1_handle;
#if USE_ADC2
adc_oneshot_unit_handle_t adc2_handle;
#endif

//校准参数
adc_cali_handle_t adc1_cali_chan0_handle = NULL;
adc_cali_handle_t adc1_cali_chan1_handle = NULL;
adc_cali_handle_t adc1_cali_chan2_handle = NULL;
adc_cali_handle_t adc1_cali_chan3_handle = NULL;
adc_cali_handle_t adc1_cali_chan4_handle = NULL;
adc_cali_handle_t adc1_cali_chan5_handle = NULL;
adc_cali_handle_t adc1_cali_chan6_handle = NULL;
adc_cali_handle_t adc1_cali_chan7_handle = NULL;
adc_cali_handle_t adc1_cali_chan8_handle = NULL;
#if USE_ADC2
adc_cali_handle_t adc2_cali_chan4_handle = NULL;
#endif

uint32_t adc1_read(uint32_t channel,int times)//返回ADC读取电压值
{
    uint32_t temp_val = 0;
    int num = 0;
    for(int i=0;i<times;i++)
    {   
        adc_oneshot_read(adc1_handle, channel,&num);
        temp_val += num;
        vTaskDelay(5);
    }
    return temp_val/times; 
}
uint32_t adc2_read(uint32_t channel,int times)//返回ADC2读取电压值
{   
    #if USE_ADC2
    uint32_t temp_val = 0;
    int num = 0;
    for(int i=0;i<times;i++)
    {
        adc_oneshot_read(adc2_handle, channel,&num); 
        temp_val += num;
        vTaskDelay(5);
    }
    return temp_val/times;
    #else
    return 0;
    #endif
}

void ADC_NTC0_Init(void)//柜体温度检测
{
adc_oneshot_chan_cfg_t config = {
    .bitwidth = ADC_BITWIDTH_DEFAULT,
    .atten = ADC_ATTEN_DB_12,
};
    adc_oneshot_config_channel(adc1_handle, NTC0_CHANNEL, &config);    
    example_adc_calibration_init(ADC_UNIT_1, NTC0_CHANNEL, ADC_ATTEN_DB_12, &adc1_cali_chan0_handle);
}
void ADC_NTCTA_Init(void)//环境温度检测
{
    adc_oneshot_chan_cfg_t config = {
    .bitwidth = ADC_BITWIDTH_DEFAULT,
    .atten = ADC_ATTEN_DB_12,
};
    adc_oneshot_config_channel(adc1_handle, NTC_TA_CHANNEL, &config);
    example_adc_calibration_init(ADC_UNIT_1, NTC_TA_CHANNEL, ADC_ATTEN_DB_12, &adc1_cali_chan3_handle);
}
void ADC_NTC1_Init(void)//蒸发风机温度检测
{
    adc_oneshot_chan_cfg_t config = {
    .bitwidth = ADC_BITWIDTH_DEFAULT,
    .atten = ADC_ATTEN_DB_12,
};
    adc_oneshot_config_channel(adc1_handle, NTC1_CHANNEL, &config);
    example_adc_calibration_init(ADC_UNIT_1, NTC1_CHANNEL, ADC_ATTEN_DB_12, &adc1_cali_chan6_handle);
}
void ADC_NTC2_Init(void)//冷凝温度检测
{
adc_oneshot_chan_cfg_t config = {
    .bitwidth = ADC_BITWIDTH_DEFAULT,
    .atten = ADC_ATTEN_DB_12,
};
    adc_oneshot_config_channel(adc1_handle, NTC2_CHANNEL, &config);
    example_adc_calibration_init(ADC_UNIT_1, NTC2_CHANNEL, ADC_ATTEN_DB_12, &adc1_cali_chan7_handle);
}
void ADC_battery_Init(void)//ADC检测电池电压（拉低BAT_EN后进行检测）
{  adc_oneshot_chan_cfg_t config = {
    .bitwidth = ADC_BITWIDTH_DEFAULT,
    .atten = ADC_ATTEN_DB_12,
};
    adc_oneshot_config_channel(adc1_handle, ADC_BATTERY_CHANNEL, &config);
    example_adc_calibration_init(ADC_UNIT_1, ADC_BATTERY_CHANNEL, ADC_ATTEN_DB_12, &adc1_cali_chan1_handle);
}
void ADC_VN0_Init(void)//ADC检测硬件版本号
{
    #if USE_ADC2
 adc_oneshot_chan_cfg_t config = {
    .bitwidth = ADC_BITWIDTH_DEFAULT,
    .atten = ADC_ATTEN_DB_12,
};
    adc_oneshot_config_channel(adc2_handle, ADC_VN0_CHANNEL, &config);
    example_adc_calibration_init(ADC_UNIT_2, ADC_VN0_CHANNEL, ADC_ATTEN_DB_12, &adc2_cali_chan4_handle);
    #endif
}
void ADC_LIGHT_Init(void)//灯光电流检测
{
  adc_oneshot_chan_cfg_t config = {
    .bitwidth = ADC_BITWIDTH_DEFAULT,
    .atten = ADC_ATTEN_DB_12,
};
    adc_oneshot_config_channel(adc1_handle, ADC_LIGHT_CHANNEL, &config);
    example_adc_calibration_init(ADC_UNIT_1, ADC_LIGHT_CHANNEL, ADC_ATTEN_DB_12, &adc1_cali_chan4_handle);
}
void _24V_INT_Init(void)//外部电压检测
{
  adc_oneshot_chan_cfg_t config = {
    .bitwidth = ADC_BITWIDTH_DEFAULT,
    .atten = ADC_ATTEN_DB_12,
};
    adc_oneshot_config_channel(adc1_handle, ADC_24V_INT_CHANNEL, &config);
    example_adc_calibration_init(ADC_UNIT_1, ADC_24V_INT_CHANNEL, ADC_ATTEN_DB_12, &adc1_cali_chan2_handle);    
}

void _3_3v_INT_Init(void)
{
      adc_oneshot_chan_cfg_t config = {
    .bitwidth = ADC_BITWIDTH_DEFAULT,
    .atten = ADC_ATTEN_DB_12,
};
    adc_oneshot_config_channel(adc1_handle, ADC_3_3V_IN_CHANNEL, &config);
    example_adc_calibration_init(ADC_UNIT_1, ADC_3_3V_IN_CHANNEL, ADC_ATTEN_DB_12, &adc1_cali_chan8_handle);   
}

double adc_light_read(void)
{
    uint16_t vtg_tmp;
	float ntc_vtg;
    int voltage=0;
    vtg_tmp = adc1_read(ADC_LIGHT_CHANNEL,SAMPLE_NUM);
    ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_chan4_handle, vtg_tmp, &voltage));
    ntc_vtg = (float)voltage/1000;

    double I1 = ntc_vtg*2/(47+2)/0.01;
    printf("light v = %dmv I = %f A\n",voltage, I1);
    return I1;
}

double adc_vn0_read(void)
{
    #if USE_ADC2
    uint16_t vtg_tmp;
	float ntc_vtg;
    int voltage=0;
    vtg_tmp = adc2_read(ADC_VN0_CHANNEL,SAMPLE_NUM);
    ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc2_cali_chan4_handle, vtg_tmp, &voltage));
    ntc_vtg = (float)voltage/1000;
    
    printf("adc_vn0_read v = %d mv tmp = %d \n",voltage,vtg_tmp);
    return ntc_vtg;
    #else
    return 0;
    #endif
}

double _24V_INT_Read(void)
{
    uint16_t vtg_tmp;
	float ntc_vtg;
    int voltage=0;
    vtg_tmp = adc1_read(ADC_24V_INT_CHANNEL,SAMPLE_NUM);
    ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_chan2_handle, vtg_tmp, &voltage));
    
    ntc_vtg = ((((float)voltage/1000)/220)*1500+(float)voltage/1000);

    // printf("24v = %f\n",ntc_vtg);
    return ntc_vtg;
}

double _3_3V_INT_Read(void)
{    
    uint16_t vtg_tmp;
	float ntc_vtg;
    int voltage=0;
    vtg_tmp = adc1_read(ADC_3_3V_IN_CHANNEL,SAMPLE_NUM);
    ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_chan8_handle, vtg_tmp, &voltage));
    ntc_vtg = (float)voltage/1000;
    
    printf("_3_3V_INT_Read v = %d mv tmp = %d \n",voltage,vtg_tmp);
    return ntc_vtg;
}

double read_battery_voltage(void)
{   
    BAT_EN_OFF;
    vTaskDelay(20);
    uint16_t vtg_tmp;
	float ntc_vtg;
    int voltage=0;
    vtg_tmp = adc1_read(ADC_BATTERY_CHANNEL,SAMPLE_NUM);
    ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_chan1_handle, vtg_tmp, &voltage));
    ntc_vtg = ((((float)voltage)/680)*330+(float)voltage)/1000;

    BAT_EN_ON;
    
    printf("read_battery_voltage v = %f v tmp = %d voltage = %d\n",ntc_vtg,vtg_tmp,voltage);
    return ntc_vtg;
}

float ntc0_get_vtg(void)
{
    uint16_t vtg_tmp;
	float ntc_vtg;
    int voltage=0;
    vtg_tmp = adc1_read(NTC0_CHANNEL,SAMPLE_NUM);
    ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_chan0_handle, vtg_tmp, &voltage));
    ntc_vtg = (float)voltage/1000;
    //printf("ntc0_get_vtg v = %f v tmp = %d voltage = %d\n",ntc_vtg,vtg_tmp,voltage);
	return ntc_vtg;
}
double ntc0_get_temp(void)
{
	double vol_t,ntc_temp = 0;
	vol_t = (double)ntc0_get_vtg();
    double R = (7500.0*(3.32-vol_t))/vol_t - 1000;
    ntc_temp = (double)(1/(log(R/NTC_R_NORMAL)/NTC_B + 1/NTC_T_NORMAL_K) - 273.15);
    // printf("vol_t = %f temp = %f\n", vol_t, ntc_temp);
	return ntc_temp;
}

float ntc1_get_vtg(void)
{
    uint16_t vtg_tmp;
	float ntc_vtg;
    int voltage=0;
    vtg_tmp = adc1_read(NTC1_CHANNEL,SAMPLE_NUM);
    ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_chan6_handle, vtg_tmp, &voltage));
    ntc_vtg = (float)voltage/1000;
	return ntc_vtg;
}
double ntc1_get_temp(void)
{
    double vol_t,ntc_temp = 0;
	vol_t = (double)ntc1_get_vtg();
    double R = (100000.0*(3.3-vol_t))/vol_t - 1000;
    ntc_temp = (double)(1/(log(R/NTC_R_NORMAL)/NTC_B + 1/NTC_T_NORMAL_K) - 273.15);
	return ntc_temp;
}

float ntc2_get_vtg(void)
{
    uint16_t vtg_tmp;
	float ntc_vtg;
    int voltage=0;
    vtg_tmp = adc1_read(NTC2_CHANNEL,SAMPLE_NUM);
    ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_chan7_handle, vtg_tmp, &voltage));
    ntc_vtg = (float)voltage/1000;
	return ntc_vtg;
}
double ntc2_get_temp(void)
{
    double vol_t,ntc_temp = 0;
	vol_t = (double)ntc2_get_vtg();
    double R = (100000.0*(3.3-vol_t))/vol_t - 1000;
    ntc_temp = (double)(1/(log(R/NTC_R_NORMAL)/NTC_B + 1/NTC_T_NORMAL_K) - 273.15);
	return ntc_temp;
}

double get_NTCrx(void)
{
    double ntc_temp = 0;
    uint16_t vtg_tmp;
    int voltage=0;
    vtg_tmp = adc1_read(NTC_TA_CHANNEL,SAMPLE_NUM);
    ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_chan3_handle, vtg_tmp, &voltage));

    float U0 = (float)voltage/1000;
    // double I = U0/100000.0;
    // double U1 = 1000.0*I;
    // double Ux = 3.3-U1-U0;
    // double R = Ux/I;
    double R = (7500.0*(3.32-U0))/U0 - 1000;
    ntc_temp = (double)(1/(log(R/NTC_R_NORMAL)/NTC_B + 1/NTC_T_NORMAL_K) - 273.15);
    
    // printf("ntc_temp v = %f v tmp = %d voltage = %d\n",ntc_temp,vtg_tmp,voltage);
    return ntc_temp;
}

//校准
bool example_adc_calibration_init(adc_unit_t unit, adc_channel_t channel, adc_atten_t atten, adc_cali_handle_t *out_handle)
{
    adc_cali_handle_t handle = NULL;
    esp_err_t ret = ESP_FAIL;
    bool calibrated = false;

#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
    if (!calibrated) {
        GEMINAI_LOGI(TAG, "calibration scheme version is %s", "Curve Fitting");
        adc_cali_curve_fitting_config_t cali_config = {
            .unit_id = unit,
            .chan = channel,
            .atten = atten,
            .bitwidth = ADC_BITWIDTH_DEFAULT,
        };
        ret = adc_cali_create_scheme_curve_fitting(&cali_config, &handle);
        if (ret == ESP_OK) {
            calibrated = true;
        }
    }
#endif


#if ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
    if (!calibrated) {
        GEMINAI_LOGI(TAG, "calibration scheme version is %s", "Line Fitting");
        adc_cali_line_fitting_config_t cali_config = {
            .unit_id = unit,
            .atten = atten,
            .bitwidth = ADC_BITWIDTH_DEFAULT,
        };
        ret = adc_cali_create_scheme_line_fitting(&cali_config, &handle);
        if (ret == ESP_OK) {
            calibrated = true;
        }
    }
#endif

    *out_handle = handle;
    if (ret == ESP_OK) {
        GEMINAI_LOGI(TAG, "Calibration Success");
    } else if (ret == ESP_ERR_NOT_SUPPORTED || !calibrated) {
        GEMINAI_LOGW(TAG, "eFuse not burnt, skip software calibration");
    } else {
        GEMINAI_LOGE(TAG, "Invalid arg or no memory");
    }

    return calibrated;
}

void example_adc_calibration_deinit(adc_cali_handle_t handle)
{
#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
    GEMINAI_LOGI(TAG, "deregister %s calibration scheme", "Curve Fitting");
    ESP_ERROR_CHECK(adc_cali_delete_scheme_curve_fitting(handle));

#elif ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
    GEMINAI_LOGI(TAG, "deregister %s calibration scheme", "Line Fitting");
    ESP_ERROR_CHECK(adc_cali_delete_scheme_line_fitting(handle));
#endif
}

void adc_calibration_deini_LIGHT(void)
{
    example_adc_calibration_deinit(adc1_cali_chan4_handle);
}

void adc_init(void)
{    
    adc_oneshot_unit_init_cfg_t adc1_pattern_cfg = {
    .unit_id = ADC_UNIT_1,
    .ulp_mode = ADC_ULP_MODE_DISABLE,
    };
    ESP_ERROR_CHECK(adc_oneshot_new_unit(&adc1_pattern_cfg, &adc1_handle));
    #if USE_ADC2
    adc_oneshot_unit_init_cfg_t adc2_pattern_cfg = {
        .unit_id = ADC_UNIT_2,
        .ulp_mode = ADC_ULP_MODE_DISABLE,
    };
    ESP_ERROR_CHECK(adc_oneshot_new_unit(&adc2_pattern_cfg, &adc2_handle));
    #endif
    
	ADC_NTC0_Init();//柜内温度探头
	ADC_NTCTA_Init();//环境温度探头
    ADC_battery_Init();
    _24V_INT_Init();
    ADC_LIGHT_Init();
}

// 根据电压计算剩余容量
int calculate_remaining_capacity(void) 
{
    float voltage = read_battery_voltage();
    if (voltage >= 4.16) {               return 100;
    } else if (voltage >= 4.15) {        return 99;
    } else if (voltage >= 4.14) {        return 97;
    } else if (voltage >= 4.12) {        return 95;
    } else if (voltage >= 4.10) {        return 92;
    } else if (voltage >= 4.08) {        return 90;
    } else if (voltage >= 4.05) {        return 87;
    } else if (voltage >= 4.03) {        return 85;
    } else if (voltage >= 3.97) {        return 80;
    } else if (voltage >= 3.93) {        return 75;
    } else if (voltage >= 3.90) {        return 70;
    } else if (voltage >= 3.87) {        return 65;
    } else if (voltage >= 3.84) {        return 60;
    } else if (voltage >= 3.81) {        return 55;
    } else if (voltage >= 3.79) {        return 50;
    } else if (voltage >= 3.77) {        return 45;
    } else if (voltage >= 3.76) {        return 42;
    } else if (voltage >= 3.74) {        return 40;
    } else if (voltage >= 3.73) {        return 35;
    } else if (voltage >= 3.72) {        return 30;
    } else if (voltage >= 3.71) {        return 25;
    } else if (voltage >= 3.69) {        return 20;
    } else if (voltage >= 3.66) {        return 15;
    } else if (voltage >= 3.65) {        return 12;
    } else if (voltage >= 3.64) {        return 10;
    } else if (voltage >= 3.63) {        return 8;
    } else if (voltage >= 3.61) {        return 5;
    } else if (voltage >= 3.59) {        return 3;
    } else {
        return 0;
    }
}
